home *** CD-ROM | disk | FTP | other *** search
/ PC World 2008 September / PCWorld_2008-09_cd.bin / v cisle / sadanastroju / lightning-0.8-tb-win.xpi / chrome / calendar.jar / content / calendar / sun-calendar-event-dialog-recurrence.js < prev    next >
Text File  |  2008-02-18  |  22KB  |  574 lines

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3.  *
  4.  * The contents of this file are subject to the Mozilla Public License Version
  5.  * 1.1 (the "License"); you may not use this file except in compliance with
  6.  * the License. You may obtain a copy of the License at
  7.  * http://www.mozilla.org/MPL/
  8.  *
  9.  * Software distributed under the License is distributed on an "AS IS" basis,
  10.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11.  * for the specific language governing rights and limitations under the
  12.  * License.
  13.  *
  14.  * The Original Code is Oracle Corporation code.
  15.  *
  16.  * The Initial Developer of the Original Code is Oracle Corporation
  17.  * Portions created by the Initial Developer are Copyright (C) 2005
  18.  * the Initial Developer. All Rights Reserved.
  19.  *
  20.  * Contributor(s):
  21.  *   Stuart Parmenter <stuart.parmenter@oracle.com>
  22.  *   Joey Minta <jminta@gmail.com>
  23.  *   Michael Buettner <michael.buettner@sun.com>
  24.  *
  25.  * Alternatively, the contents of this file may be used under the terms of
  26.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  27.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28.  * in which case the provisions of the GPL or the LGPL are applicable instead
  29.  * of those above. If you wish to allow use of your version of this file only
  30.  * under the terms of either the GPL or the LGPL, and not to allow others to
  31.  * use your version of this file under the terms of the MPL, indicate your
  32.  * decision by deleting the provisions above and replace them with the notice
  33.  * and other provisions required by the GPL or the LGPL. If you do not delete
  34.  * the provisions above, a recipient may use your version of this file under
  35.  * the terms of any one of the MPL, the GPL or the LGPL.
  36.  *
  37.  * ***** END LICENSE BLOCK ***** */
  38.  
  39. var gIsReadOnly = false;
  40. var gStartTime = null;
  41. var gEndTime = null;
  42.  
  43. function onLoad() {
  44.     var args = window.arguments[0];
  45.     var item = args.calendarEvent;
  46.     var calendar = item.calendar;
  47.     var recinfo = args.recurrenceInfo;
  48.  
  49.     gStartTime = args.startTime;
  50.     gEndTime = args.endTime;
  51.     var preview = document.getElementById("recurrence-preview");
  52.     preview.dateTime = gStartTime.getInTimezone(calendarDefaultTimezone());
  53.  
  54.     onChangeCalendar(calendar);
  55.  
  56.     // Set starting value for 'repeat until' rule.
  57.     setElementValue("repeat-until-date", gStartTime.getInTimezone(floating()).jsDate);
  58.  
  59.     if (item.parentItem != item) {
  60.         item = item.parentItem;
  61.     }
  62.     var rule = null;
  63.     if (recinfo) {
  64.         // Split out rules and exceptions
  65.         try {
  66.             var rrules = splitRecurrenceRules(recinfo);
  67.             var rules = rrules[0];
  68.             var exceptions = rrules[1];
  69.             // Deal with the rules
  70.             if (rules.length > 0) {
  71.                 // We only handle 1 rule currently
  72.                 if (rules[0] instanceof Components.interfaces.calIRecurrenceRule) {
  73.                     rule = rules[0];
  74.                 }
  75.             }
  76.         } catch (ex) {
  77.             Component.utils.reportError(ex);
  78.         }
  79.     }
  80.     if (!rule) {
  81.         rule = createRecurrenceRule();
  82.         rule.type = 'DAILY';
  83.         rule.interval = 1;
  84.         rule.count = -1;
  85.     }
  86.     initializeControls(rule);
  87.  
  88.     // Update controls
  89.     updateRecurrenceDeck();
  90.  
  91.     opener.setCursor("auto");
  92.     self.focus();
  93. }
  94.  
  95. function initializeControls(rule) {
  96.     function getOrdinalAndWeekdayOfRule(aByDayRuleComponent) {
  97.         return {
  98.             ordinal: (aByDayRuleComponent - (aByDayRuleComponent % 8)) / 8,
  99.             weekday: Math.abs(aByDayRuleComponent % 8)
  100.         };
  101.     }
  102.     
  103.     switch (rule.type) {
  104.         case "DAILY":
  105.             document.getElementById("period-list").selectedIndex = 0;
  106.             setElementValue("daily-days", rule.interval);
  107.             break;
  108.         case "WEEKLY":
  109.             setElementValue("weekly-weeks", rule.interval);
  110.             document.getElementById("period-list").selectedIndex = 1;
  111.             break;
  112.         case "MONTHLY":
  113.             setElementValue("monthly-interval", rule.interval);
  114.             document.getElementById("period-list").selectedIndex = 2;
  115.             break;
  116.         case "YEARLY":
  117.             setElementValue("yearly-interval", rule.interval);
  118.             document.getElementById("period-list").selectedIndex = 3;
  119.             break;
  120.         default:
  121.             document.getElementById("period-list").selectedIndex = 0;
  122.             dump("unable to handle your rule type!\n");
  123.             break;
  124.     }
  125.  
  126.     var byDayRuleComponent = rule.getComponent("BYDAY", {});
  127.     var byMonthDayRuleComponent = rule.getComponent("BYMONTHDAY", {});
  128.     var byMonthRuleComponent = rule.getComponent("BYMONTH", {});
  129.     var kDefaultTimezone = calendarDefaultTimezone();
  130.     var startDate = gStartTime.getInTimezone(kDefaultTimezone);
  131.  
  132.     // "DAILY" ruletype
  133.     // byDayRuleComponents may have been set priorily by "MONTHLY"- ruletypes
  134.     // where they have a different context-
  135.     // that's why we also query the current rule-type
  136.     if (byDayRuleComponent.length == 0  || rule.type != "DAILY") {
  137.         document.getElementById("daily-group").selectedIndex = 0;
  138.     } else {
  139.         document.getElementById("daily-group").selectedIndex = 1;
  140.     }
  141.  
  142.     // "WEEKLY" ruletype
  143.     if (byDayRuleComponent.length == 0 || rule.type != "WEEKLY") {
  144.         document.getElementById("daypicker-weekday").days = [startDate.weekday + 1];
  145.     } else {
  146.         document.getElementById("daypicker-weekday").days = byDayRuleComponent;
  147.     }
  148.  
  149.     // "MONTHLY" ruletype
  150.     var ruleComponentsEmpty = (byDayRuleComponent.length == 0 &&
  151.                                byMonthDayRuleComponent.length == 0);
  152.     if (ruleComponentsEmpty || rule.type != "MONTHLY") {
  153.         document.getElementById("monthly-group").selectedIndex = 1;
  154.         document.getElementById("monthly-days").days = [startDate.day];
  155.         var day = Math.floor((startDate.day - 1) / 7) + 1;
  156.         setElementValue("monthly-ordinal", day);
  157.         setElementValue("monthly-weekday", startDate.weekday + 1);
  158.     } else {
  159.         if (byDayRuleComponent.length > 0) {
  160.             document.getElementById("monthly-group").selectedIndex = 0;
  161.             var ruleInfo = getOrdinalAndWeekdayOfRule(byDayRuleComponent[0]);
  162.             setElementValue("monthly-ordinal", ruleInfo.ordinal);
  163.             setElementValue("monthly-weekday", ruleInfo.weekday);
  164.         } else if (byMonthDayRuleComponent.length > 0) {
  165.             if (byMonthDayRuleComponent.length == 1 && byDayRuleComponent[0] == -1) {
  166.                 document.getElementById("monthly-group").selectedIndex = 0;
  167.                 setElementValue("monthly-ordinal", byMonthDayRuleComponent[0]);
  168.                 setElementValue("monthly-weekday", byMonthDayRuleComponent[0]);
  169.             } else {
  170.                 document.getElementById("monthly-group").selectedIndex = 1;
  171.                 document.getElementById("monthly-days").days = byMonthDayRuleComponent;
  172.             }
  173.         }
  174.     }
  175.  
  176.     // "YEARLY" ruletype
  177.     if (byMonthRuleComponent.length == 0  || rule.type != "YEARLY") {
  178.         setElementValue("yearly-days", startDate.day);
  179.         setElementValue("yearly-month-ordinal", startDate.month + 1);
  180.         var day = Math.floor((startDate.day - 1) / 7) + 1;
  181.         setElementValue("yearly-ordinal", day);
  182.         setElementValue("yearly-weekday", startDate.weekday + 1);
  183.         setElementValue("yearly-month-rule", startDate.month + 1);
  184.     } else {
  185.         if (byMonthDayRuleComponent.length > 0) {
  186.             document.getElementById("yearly-group").selectedIndex = 0;
  187.             setElementValue("yearly-month-ordinal", byMonthRuleComponent[0]);
  188.             setElementValue("yearly-days", byMonthDayRuleComponent[0]);
  189.         } else if (byDayRuleComponent.length > 0) {
  190.             document.getElementById("yearly-group").selectedIndex = 1;
  191.             var ruleInfo = getOrdinalAndWeekdayOfRule(byDayRuleComponent[0]);
  192.             setElementValue("yearly-ordinal", ruleInfo.ordinal);
  193.             setElementValue("yearly-weekday", ruleInfo.weekday);
  194.             setElementValue("yearly-month-rule", byMonthRuleComponent[0]);
  195.         }
  196.     }
  197.  
  198.     /* load up the duration of the event radiogroup */
  199.     if (rule.isByCount) {
  200.         if (rule.count == -1) {
  201.             setElementValue("recurrence-duration", "forever");
  202.         } else {
  203.             setElementValue("recurrence-duration", "ntimes");
  204.             setElementValue("repeat-ntimes-count", rule.count );
  205.         }
  206.     } else {
  207.         var endDate = rule.endDate;
  208.         if (!endDate) {
  209.             setElementValue("recurrence-duration", "forever");
  210.         } else {
  211.             endDate = endDate.getInTimezone(gStartTime.timezone); // calIRecurrenceRule::endDate is always UTC or floating
  212.             setElementValue("recurrence-duration", "until");
  213.             setElementValue("repeat-until-date", endDate.getInTimezone(floating()).jsDate);
  214.         }
  215.     }
  216. }
  217.  
  218. function onSave(item) {
  219.     // Always return 'null' if this item is an occurrence.
  220.     if (!item || item.parentItem != item) {
  221.         return null;
  222.     }
  223.  
  224.     // This works, but if we ever support more complex recurrence,
  225.     // e.g. recurrence for Martians, then we're going to want to
  226.     // not clone and just recreate the recurrenceInfo each time.
  227.     // The reason is that the order of items (rules/dates/datesets)
  228.     // matters, so we can't always just append at the end.  This
  229.     // code here always inserts a rule first, because all our
  230.     // exceptions should come afterward.
  231.     var deckNumber = Number(getElementValue("period-list"));
  232.  
  233.     var args = window.arguments[0];
  234.     var recurrenceInfo = args.recurrenceInfo;
  235.     if (recurrenceInfo) {
  236.         recurrenceInfo = recurrenceInfo.clone();
  237.         var rrules = splitRecurrenceRules(recurrenceInfo);
  238.         if (rrules[0].length > 0) {
  239.             recurrenceInfo.deleteRecurrenceItem(rrules[0][0]);
  240.         }
  241.         recurrenceInfo.item = item;
  242.     } else {
  243.         recurrenceInfo = createRecurrenceInfo(item);
  244.     }
  245.  
  246.     var recRule = createRecurrenceRule();
  247.     switch (deckNumber) {
  248.     case 0:
  249.         recRule.type = "DAILY";
  250.         var dailyGroup = document.getElementById("daily-group");
  251.         if (dailyGroup.selectedIndex == 0) {
  252.             var ndays = Math.max(1, Number(getElementValue("daily-days")));
  253.             recRule.interval = ndays;
  254.         } else {
  255.             recRule.interval = 1;
  256.             var onDays = [2, 3, 4, 5, 6];
  257.             recRule.setComponent("BYDAY", onDays.length, onDays);
  258.         }
  259.         break;
  260.     case 1:
  261.         recRule.type = "WEEKLY";
  262.         var ndays = Number(getElementValue("weekly-weeks"));
  263.         recRule.interval = ndays;
  264.         var onDays = document.getElementById("daypicker-weekday").days;
  265.         if (onDays.length > 0) {
  266.             recRule.setComponent("BYDAY", onDays.length, onDays);
  267.         }
  268.         break;
  269.     case 2:
  270.         recRule.type = "MONTHLY";
  271.         var monthInterval = Number(getElementValue("monthly-interval"));
  272.         recRule.interval = monthInterval;
  273.         var monthlyGroup = document.getElementById("monthly-group");
  274.         if (monthlyGroup.selectedIndex==0) {
  275.             var ordinal = Number(getElementValue("monthly-ordinal"));
  276.             var day_of_week = Number(getElementValue("monthly-weekday"));
  277.             if (day_of_week < 0) {
  278.                 recRule.setComponent("BYMONTHDAY", 1, [ ordinal ]);
  279.             } else {
  280.                 var sign = ordinal < 0 ? -1 : 1;
  281.                 var onDays = [ (Math.abs(ordinal) * 8 + day_of_week) * sign ];
  282.                 recRule.setComponent("BYDAY", onDays.length, onDays);
  283.             }
  284.         } else {
  285.             var monthlyDays = document.getElementById("monthly-days").days;
  286.             if (monthlyDays.length > 0) {
  287.                 recRule.setComponent("BYMONTHDAY", monthlyDays.length, monthlyDays);
  288.             }
  289.         }
  290.         break;
  291.     case 3:
  292.         recRule.type = "YEARLY";
  293.         var yearInterval = Number(getElementValue("yearly-interval"));
  294.         recRule.interval = yearInterval;
  295.         var yearlyGroup = document.getElementById("yearly-group");
  296.         if (yearlyGroup.selectedIndex == 0) {
  297.             var yearlyByMonth = [ Number(getElementValue("yearly-month-ordinal")) ];
  298.             recRule.setComponent("BYMONTH", yearlyByMonth.length, yearlyByMonth);
  299.             var yearlyByDay = [ Number(getElementValue("yearly-days")) ];
  300.             recRule.setComponent("BYMONTHDAY", yearlyByDay.length, yearlyByDay);
  301.         } else {
  302.             var yearlyByMonth = [ Number(getElementValue("yearly-month-rule")) ];
  303.             recRule.setComponent("BYMONTH", yearlyByMonth.length, yearlyByMonth);
  304.             var ordinal = Number(getElementValue("yearly-ordinal"));
  305.             var day_of_week = Number(getElementValue("yearly-weekday"));
  306.             var sign = ordinal < 0 ? -1 : 1;
  307.             var onDays = [ (Math.abs(ordinal) * 8 + day_of_week) * sign ];
  308.             recRule.setComponent("BYDAY", onDays.length, onDays);
  309.         }
  310.         break;
  311.     }
  312.  
  313.     // Figure out how long this event is supposed to last
  314.     switch (document.getElementById("recurrence-duration").selectedItem.value) {
  315.         case "forever":
  316.             recRule.count = -1;
  317.             break;
  318.         case "ntimes":
  319.             recRule.count = Math.max(1, getElementValue("repeat-ntimes-count"));
  320.             break;
  321.         case "until":
  322.             var endDate = jsDateToDateTime(getElementValue("repeat-until-date"), gStartTime.timezone);
  323.             endDate.isDate = gStartTime.isDate; // enforce same value type as DTSTART
  324.             if (!gStartTime.isDate) {
  325.                 // correct UNTIL to exactly match start date's hour, minute, second:
  326.                 endDate.hour = gStartTime.hour;
  327.                 endDate.minute = gStartTime.minute;
  328.                 endDate.second = gStartTime.second;
  329.             }
  330.             recRule.endDate = endDate;
  331.             break;
  332.     }
  333.  
  334.     if (recRule.interval < 1) {
  335.         return null;
  336.     }
  337.  
  338.     recurrenceInfo.insertRecurrenceItemAt(recRule, 0);
  339.     return recurrenceInfo;
  340. }
  341.  
  342. function onAccept() {
  343.     var args = window.arguments[0];
  344.     var item = args.calendarEvent;
  345.     args.onOk(onSave(item));
  346.     return true;
  347. }
  348.  
  349. function onChangeCalendar(calendar) {
  350.     var args = window.arguments[0];
  351.     var item = args.calendarEvent;
  352.  
  353.     // Set 'gIsReadOnly' if the calendar is read-only
  354.     gIsReadOnly = false;
  355.     if (calendar && calendar.readOnly) {
  356.         gIsReadOnly = true;
  357.     }
  358.  
  359.     // Disable or enable controls based on a set or rules
  360.     // - whether this item is a stand-alone item or an occurrence
  361.     // - whether or not this item is read-only
  362.     // - whether or not the state of the item allows recurrence rules
  363.     //     - tasks without an entrydate are invalid
  364.     disableOrEnable(item);
  365.  
  366.     updateRecurrenceControls();
  367. }
  368.  
  369. function disableOrEnable(item) {
  370.     if (item.parentItem != item) {
  371.        disableRecurrenceFields("disable-on-occurrence");
  372.     } else if (gIsReadOnly) {
  373.         disableRecurrenceFields("disable-on-readonly");
  374.     } else if (isToDo(item) && !gStartTime) {
  375.         disableRecurrenceFields("disable-on-readonly");
  376.     } else {
  377.         enableRecurrenceFields("disable-on-readonly");
  378.     }
  379. }
  380.  
  381. function disableRecurrenceFields(aAttributeName) {
  382.     var disableElements = document.getElementsByAttribute(aAttributeName, "true");
  383.     for (var i = 0; i < disableElements.length; i++) {
  384.         disableElements[i].setAttribute('disabled', 'true');
  385.     }
  386. }
  387.  
  388. function enableRecurrenceFields(aAttributeName) {
  389.     var enableElements = document.getElementsByAttribute(aAttributeName, "true");
  390.     for (var i = 0; i < enableElements.length; i++) {
  391.         enableElements[i].removeAttribute('disabled');
  392.     }
  393. }
  394.  
  395. function splitRecurrenceRules(recurrenceInfo) {
  396.     var ritems = recurrenceInfo.getRecurrenceItems({});
  397.     var rules = [];
  398.     var exceptions = [];
  399.     for each (var r in ritems) {
  400.         if (r.isNegative) {
  401.             exceptions.push(r);
  402.         } else {
  403.             rules.push(r);
  404.         }
  405.     }
  406.     return [rules, exceptions];
  407. }
  408.  
  409. function updateRecurrenceDeck() {
  410.     document.getElementById("period-deck")
  411.             .selectedIndex = Number(getElementValue("period-list"));
  412.     updateRecurrenceControls();
  413. }
  414.  
  415. function updateRecurrenceRange() {
  416.     var args = window.arguments[0];
  417.     var item = args.calendarEvent;
  418.     if (item.parentItem != item || gIsReadOnly) {
  419.         return;
  420.     }
  421.  
  422.     var radioRangeForever =
  423.         document.getElementById("recurrence-range-forever");
  424.     var radioRangeFor =
  425.         document.getElementById("recurrence-range-for");
  426.     var radioRangeUntil =
  427.         document.getElementById("recurrence-range-until");
  428.     var rangeTimesCount =
  429.         document.getElementById("repeat-ntimes-count");
  430.     var rangeUntilDate =
  431.         document.getElementById("repeat-until-date");
  432.     var rangeAppointmentsLabel =
  433.         document.getElementById("repeat-appointments-label");
  434.  
  435.     var deckNumber = Number(getElementValue("period-list"));
  436.  
  437.     radioRangeForever.removeAttribute("disabled");
  438.     radioRangeFor.removeAttribute("disabled");
  439.     radioRangeUntil.removeAttribute("disabled");
  440.     rangeAppointmentsLabel.removeAttribute("disabled");
  441.  
  442.     var durationSelection = document.getElementById("recurrence-duration")
  443.                                     .selectedItem.value;
  444.     if (durationSelection == "forever") {
  445.     }
  446.  
  447.     if (durationSelection == "ntimes") {
  448.         rangeTimesCount.removeAttribute("disabled");
  449.     } else {
  450.         rangeTimesCount.setAttribute("disabled", "true");
  451.     }
  452.  
  453.     if (durationSelection == "until") {
  454.         rangeUntilDate.removeAttribute("disabled");
  455.     } else {
  456.         rangeUntilDate.setAttribute("disabled", "true");
  457.     }
  458. }
  459.  
  460. function updatePreview() {
  461.     var args = window.arguments[0];
  462.     var item = args.calendarEvent;
  463.     if (item.parentItem != item) {
  464.         item = item.parentItem;
  465.     }
  466.  
  467.     // TODO: We should better start the whole dialog with a newly cloned item
  468.     // and always pump changes immediately into it. this would eliminate the
  469.     // need to break the encapsulation, as we do it here. but we need the item
  470.     // to contain the startdate in order to calculate the recurrence preview.
  471.     item = item.clone();
  472.     var kDefaultTimezone = calendarDefaultTimezone();
  473.     if (isEvent(item)) {
  474.         var startDate = gStartTime.getInTimezone(kDefaultTimezone);
  475.         var endDate = gEndTime.getInTimezone(kDefaultTimezone);
  476.         if (startDate.isDate) {
  477.             endDate.day--;
  478.         }
  479.  
  480.         item.startDate = startDate;
  481.         item.endDate = endDate;
  482.     }
  483.     if (isToDo(item)) {
  484.         var entryDate = gStartTime;
  485.         if (entryDate) {
  486.             entryDate = entryDate.getInTimezone(kDefaultTimezone);
  487.         } else {
  488.             item.recurrenceInfo = null;
  489.         }
  490.         item.entryDate = entryDate;
  491.         var dueDate = gEndTime;
  492.         if (dueDate) {
  493.             dueDate = dueDate.getInTimezone(kDefaultTimezone);
  494.         }
  495.         item.dueDate = dueDate;
  496.     }
  497.  
  498.     var recInfo = onSave(item);
  499.     var preview = document.getElementById("recurrence-preview");
  500.     preview.updatePreview(recInfo);
  501. }
  502.  
  503. function updateRecurrenceControls() {
  504.     updateRecurrencePattern();
  505.     updateRecurrenceRange();
  506.     updatePreview();
  507. }
  508.  
  509. /**
  510.  * Disables/enables controls related to the recurrence pattern.
  511.  * the status of the controls depends on which period entry is selected
  512.  * and which form of pattern rule is selected.
  513.  */
  514. function updateRecurrencePattern() {
  515.     var args = window.arguments[0];
  516.     var item = args.calendarEvent;
  517.     if (item.parentItem != item || gIsReadOnly) {
  518.         return;
  519.     }
  520.  
  521.     switch (Number(getElementValue("period-list"))) {
  522.         // daily
  523.         case 0:
  524.             var dailyGroup = document.getElementById("daily-group");
  525.             var dailyDays = document.getElementById("daily-days");
  526.             dailyDays.removeAttribute("disabled", "true");
  527.             if (dailyGroup.selectedIndex == 1) {
  528.                 dailyDays.setAttribute("disabled", "true");
  529.             }
  530.             break;
  531.         // weekly
  532.         case 1:
  533.             break;
  534.         // monthly
  535.         case 2:
  536.             var monthlyGroup = document.getElementById("monthly-group");
  537.             var monthlyOrdinal = document.getElementById("monthly-ordinal");
  538.             var monthlyWeekday = document.getElementById("monthly-weekday");
  539.             var monthlyDays = document.getElementById("monthly-days");
  540.             monthlyOrdinal.removeAttribute("disabled", "true");
  541.             monthlyWeekday.removeAttribute("disabled", "true");
  542.             monthlyDays.removeAttribute("disabled", "true");
  543.             if (monthlyGroup.selectedIndex == 0) {
  544.                 monthlyDays.setAttribute("disabled", "true");
  545.             } else {
  546.                 monthlyOrdinal.setAttribute("disabled", "true");
  547.                 monthlyWeekday.setAttribute("disabled", "true");
  548.             }
  549.             break;
  550.         // yearly
  551.         case 3:
  552.             var yearlyGroup = document.getElementById("yearly-group");
  553.             var yearlyDays = document.getElementById("yearly-days");
  554.             var yearlyMonthOrdinal = document.getElementById("yearly-month-ordinal");
  555.             var yearlyOrdinal = document.getElementById("yearly-ordinal");
  556.             var yearlyWeekday = document.getElementById("yearly-weekday");
  557.             var yearlyMonthRule = document.getElementById("yearly-month-rule");
  558.             yearlyDays.removeAttribute("disabled", "true");
  559.             yearlyMonthOrdinal.removeAttribute("disabled", "true");
  560.             yearlyOrdinal.removeAttribute("disabled", "true");
  561.             yearlyWeekday.removeAttribute("disabled", "true");
  562.             yearlyMonthRule.removeAttribute("disabled", "true");
  563.             if (yearlyGroup.selectedIndex == 0) {
  564.                 yearlyOrdinal.setAttribute("disabled", "true");
  565.                 yearlyWeekday.setAttribute("disabled", "true");
  566.                 yearlyMonthRule.setAttribute("disabled", "true");
  567.             } else {
  568.                 yearlyDays.setAttribute("disabled", "true");
  569.                 yearlyMonthOrdinal.setAttribute("disabled", "true");
  570.             }
  571.             break;
  572.     }
  573. }
  574.